﻿/*
 * 由SharpDevelop创建。
 * 用户： Administrator
 * 日期: 2024/9/20
 * 时间: 17:18
 * 
 * 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件
 */
using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections;

namespace NotepadSharp.Utils
{
	/// <summary>
	/// 功能函数
	/// </summary>
	internal class func
	{
		public static int WordCount(string text){
			#region 字数统计  https://blog.csdn.net/qq_40311553/article/details/134680532
            Char[] stat = text.ToCharArray();//字节数组
            int[] thre = new int[stat.Length];//空的三元数组，用于存放三元元素。
            Regex reg = new Regex(@"^[\u4e00-\u9fa5]$");//【中文汉字】正则表达式
 
            //【可计算中文符号】数组。
            string[] strC1 = { "，", "。", "、", "；", "‘", "！", "（", "）", "【", "】", "《", "》", "？", "：", "“", "”", "·" };
            string[] strC2 = { "…", "—" };//【Word】中“——”不计数量；【WPS】中“——”统计数量！
 
            ArrayList listC = new ArrayList(strC1);//使用声明的数组“strC1”，实例化一个“ArrayList”对象
            ArrayList listC2 = new ArrayList(strC2);//使用声明的数组“strC2”，实例化一个“ArrayList”对象
 
            for (int t = 0; t < thre.Length; t++)//将字节数组，转化为三元数组
            {
                if (Char.IsWhiteSpace(stat[t]) == true)
                {//将字节数组中的“空格”，转化为【0】，并存入三元数组
                    thre[t] = 0;
                }
                else if (reg.IsMatch(stat[t].ToString()) == true | listC.Contains(stat[t].ToString()) == true | listC2.Contains(stat[t].ToString()) == true)
                {//将字节数组中的“中文字符”，转化为【1】，并存入三元数组
                    thre[t] = 1;
                }
                else
                {//将字节数组中的“其它字符”（英文、数字等键盘上可输入字符），转化为【2】，并存入三元数组
                    thre[t] = 2;
                }
            }
            int w = 0;//统计空格数量（无扩展功能时，此项可省略）。
            int n = 0;//统计“中文字符”【可计算】的数量。
            int ot = 0;//统计“其它字符”【可统计】数量。
            foreach(int m in thre)//遍历三元数组，对每种元素数量，进行统计
                switch (m)
                {
                    case 0:
                        w++;//（无扩展功能时，此项可省略）
                        break;
                    case 1:
                        n++;
                        break;
                    case 2:
                        ot++;
                        break;
                    default:
                        break;
                }
            int[] pot = new int[ot];//“其它元素”位置索引数组
            int pt = 0;//位置信息数组索引
            for (int q = 0; q < thre.Length; q++)//遍历“其它字符”【可统计】数组，获取其索引
            {
                if (thre[q] == 2)
                {
                    pot[pt] = q;//将三元数组中，“其它元素”位置索引，写入到索引数组中
                    pt++;
                }
            }
            int cot = 0;//其它元素的“可计算字符”【Word 中可以被计算】的数量。
            for(int c = 0; c < pot.Length - 1; c++)
            {//将存储在位置信息数组中，【其它可计算字符】值（上步骤中三元数组中的索引），前后元素对比。
                if (pot[c + 1] - pot[c] == 1)//前后元素值差为【一】时：
                {
                    continue;//跳过此次循环。
                }
                else//前后元素值差不为【一】时：
                {
                    cot++;//其它元素的“可计算字符”【Word 中可以被计算】数量+1.
                }
            }
            if (ot > 0)//当三元数组中，其它字符”【可统计】的数量大于1时：
            {
                return (cot + 1 + n);//总的字数数量。
            }
            else//当三元数组中，其它字符”【可统计】的数量小于1时：
            {
                return (cot + n);//总的字数数量。
            }
            #endregion 
		}
		
		/// <summary>
        /// 获取文本文件的字符编码类型
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public static Encoding GetTextFileEncodingType(string fileName) 
        {
            Encoding encoding = Encoding.Default;
            FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read);
            BinaryReader binaryReader = new BinaryReader(fileStream, encoding);
            byte[] buffer = binaryReader.ReadBytes((int)fileStream.Length);
            binaryReader.Close();
            fileStream.Close();
            if (buffer.Length >= 3 && buffer[0] == 239 && buffer[1] == 187 && buffer[2] == 191)
            {
                encoding = Encoding.UTF8;
            }
            else if (buffer.Length >= 3 && buffer[0] == 254 && buffer[1] == 255 && buffer[2] == 0)
            {
                encoding = Encoding.BigEndianUnicode;
            }
            else if (buffer.Length >= 3 && buffer[0] == 255 && buffer[1] == 254 && buffer[2] == 65)
            {
                encoding = Encoding.Unicode;
            }
            else if (IsUTF8Bytes(buffer)) 
            {
                encoding = Encoding.UTF8;
            }
            return encoding;
        }
		/// <summary>
        /// 判断是否是不带 BOM 的 UTF8 格式
        /// BOM（Byte Order Mark），字节顺序标记，出现在文本文件头部，Unicode编码标准中用于标识文件是采用哪种格式的编码。
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        private static bool IsUTF8Bytes(byte[] data)
        {
            int charByteCounter = 1; //计算当前正分析的字符应还有的字节数 
            byte curByte; //当前分析的字节. 
            for (int i = 0; i < data.Length; i++)
            {
                curByte = data[i];
                if (charByteCounter == 1)
                {
                    if (curByte >= 0x80)
                    {
                        //判断当前 
                        while (((curByte <<= 1) & 0x80) != 0)
                        {
                            charByteCounter++;
                        }
                        //标记位首位若为非0 则至少以2个1开始 如:110XXXXX...........1111110X 
                        if (charByteCounter == 1 || charByteCounter > 6)
                        {
                            return false;
                        }
                    }
                }
                else
                {
                    //若是UTF-8 此时第一位必须为1 
                    if ((curByte & 0xC0) != 0x80)
                    {
                        return false;
                    }
                    charByteCounter--;
                }
            }
            if (charByteCounter > 1)
            {
                throw new Exception("非预期的byte格式");
            }
            return true;
        }         
	}
}
